package com.ourteam.workspace.api;

import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformFactory;
import org.apache.ddlutils.io.DatabaseIO;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.Table;
import org.apache.velocity.app.VelocityEngine;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ourteam.frame.controller.AbstractServiceController;
import com.ourteam.frame.web.AbstractNoQueryBeanSearchHelper;
import com.ourteam.frame.web.AbstractSearchHelper;
import com.ourteam.frame.web.GridBean;
import com.ourteam.frame.web.ProgressInfoBean;
import com.ourteam.frame.web.RequestStatus;
import com.ourteam.frame.web.TreeViewNodeBean;
import com.ourteam.product.model.api.ProductModelCodeGenerator;
import com.ourteam.product.model.dao.ProductModelCodeTemplateDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelObjectDAOQueryBean;
import com.ourteam.product.model.dao.ProductModelPropertyDAOQueryBean;
import com.ourteam.product.model.domain.ProductDatabaseBean;
import com.ourteam.product.model.domain.ProductModelCodeTemplateBean;
import com.ourteam.product.model.domain.ProductModelObjectBean;
import com.ourteam.product.model.domain.ProductModelPackageBean;
import com.ourteam.product.model.domain.ProductModelPropertyBean;
import com.ourteam.product.model.service.IProductModelService;
import com.ourteam.product.model.service.ProductModelServiceFactory;
import com.ourteam.scm.utils.DefaultSCMListener;
import com.ourteam.scm.utils.ISCMService;
import com.ourteam.scm.utils.ModuleInfoBean;
import com.ourteam.scm.utils.ResourceDiffentInfomation;
import com.ourteam.scm.utils.VersionInfo;
import com.ourteam.scm.utils.VersionLogChangePath;
import com.ourteam.scm.utils.VersionLogInformation;
import com.ourteam.sourcecode.utils.ISourceCodeCheckListtener;
import com.ourteam.sourcecode.utils.SourceCodeCheckRuleSet;
import com.ourteam.sourcecode.utils.SourceCodeCheckUtils;
import com.ourteam.sourcecode.utils.SourceLineBean;
import com.ourteam.sourcecode.utils.SourceLineCounter;
import com.ourteam.workspace.dao.IWorkspaceResourceDAO;
import com.ourteam.workspace.dao.IWorkspaceScmLogDAO;
import com.ourteam.workspace.dao.WorkspaceDAOQueryBean;
import com.ourteam.workspace.dao.WorkspaceMemberDAOQueryBean;
import com.ourteam.workspace.dao.WorkspaceProductDatabaseModelRelateDAOQueryBean;
import com.ourteam.workspace.dao.WorkspaceProductDatabaseRelateDAOQueryBean;
import com.ourteam.workspace.dao.WorkspaceResourceBusinessPackageRelateDAOQueryBean;
import com.ourteam.workspace.dao.WorkspaceResourceDAOQueryBean;
import com.ourteam.workspace.dao.WorkspaceResourceTypeEnum;
import com.ourteam.workspace.dao.WorkspaceScmLogDAOQueryBean;
import com.ourteam.workspace.domain.WorkspaceBean;
import com.ourteam.workspace.domain.WorkspaceConfigPropertyBean;
import com.ourteam.workspace.domain.WorkspaceMemberBean;
import com.ourteam.workspace.domain.WorkspaceProductDatabaseModelRelateBean;
import com.ourteam.workspace.domain.WorkspaceProductDatabaseRelateBean;
import com.ourteam.workspace.domain.WorkspaceResourceBean;
import com.ourteam.workspace.domain.WorkspaceResourceBusinessPackageRelateBean;
import com.ourteam.workspace.domain.WorkspaceScmChangePathLogBean;
import com.ourteam.workspace.domain.WorkspaceScmConfigBean;
import com.ourteam.workspace.domain.WorkspaceScmLogBean;
import com.ourteam.workspace.service.IWorkspaceService;
import com.ourteam.workspace.service.WorkspaceServiceFactory;

@Controller
@CrossOrigin
@RequestMapping("/api/WORKSPACE")
public class WorkspaceAPI extends AbstractServiceController {

	private static final IWorkspaceService WORKSPACE_SERVICE = WorkspaceServiceFactory.getWorkspaceService();

	private static final IProductModelService PRODUCT_MODEL_SERVICE = ProductModelServiceFactory
			.getProductModelService();

	@RequestMapping("/getWorkspaceList")
	@ResponseBody
	public WorkspaceBean[] getWorkspaceList() throws Exception {

		WorkspaceDAOQueryBean queryBean = new WorkspaceDAOQueryBean();

		return WORKSPACE_SERVICE.queryWorkspaces(queryBean);
	}

	@RequestMapping("/saveWorkspace")
	@ResponseBody
	public WorkspaceBean saveWorkspace(@ModelAttribute WorkspaceBean workspaceBean, HttpServletRequest request,
			Model model) throws Exception {

		if (workspaceBean.getId() != 0) {
			WORKSPACE_SERVICE.modifyWorkspace(workspaceBean);
		} else {
			WORKSPACE_SERVICE.addNewWorkspace(workspaceBean);
			File rootDir = new File(SystemUtils.USER_HOME,
					this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

			if (rootDir.exists() == false) {
				rootDir.mkdirs();
			}

		}
		return workspaceBean;
	}

	@RequestMapping("/deletWorkspace")
	@ResponseBody
	public boolean deletWorkspace(@RequestParam long workspaceId, HttpServletRequest request, Model model)
			throws Exception {

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (rootDir.exists()) {
			FileUtils.cleanDirectory(rootDir);
		}

		WORKSPACE_SERVICE.deleteWorkspace(workspaceId);

		return true;
	}

	@RequestMapping("/getWorkspaceById")
	@ResponseBody
	public WorkspaceBean getWorkspaceById(@RequestParam long id, HttpServletRequest request, Model model)
			throws Exception {

		return WORKSPACE_SERVICE.getWorkspaceById(id);

	}

	@RequestMapping("/getWorkspaceScmConfig")
	@ResponseBody
	public WorkspaceScmConfigBean getWorkspaceScmConfig(@RequestParam long workspaceId) throws Exception {

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE.getWorkspaceScmConfig(workspaceId);

		if (scmConfigBean == null) {
			scmConfigBean = new WorkspaceScmConfigBean();
			scmConfigBean.setWorkspaceId(workspaceId);
			scmConfigBean.setScmType("SVN_SERVER");
		}

		return scmConfigBean;

	}

	@RequestMapping("/saveWorkspaceScmConfig")
	@ResponseBody
	public RequestStatus saveWorkspaceScmConfig(@ModelAttribute WorkspaceScmConfigBean scmConfigBean,
			final HttpServletRequest request) throws Exception {

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		WorkspaceScmConfigBean oldScmConfigBean = WORKSPACE_SERVICE
				.getWorkspaceScmConfig(scmConfigBean.getWorkspaceId());

		final RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		if (oldScmConfigBean != null) {

			String oldSvnUrl = WorkspaceUtils.getSVNUrl(oldScmConfigBean,
					WorkspaceUtils.getModuleInfo(oldScmConfigBean));

			String newSvnUrl = WorkspaceUtils.getSVNUrl(scmConfigBean, moduleInfo);

			progressInfoBean.setId("relocalWorkspace" + scmConfigBean.getWorkspaceId());

			if (newSvnUrl.equals(oldSvnUrl) == false) {

				ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

				WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(scmConfigBean.getWorkspaceId());

				File rootDir = new File(SystemUtils.USER_HOME,
						this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

				if (rootDir.exists() == false) {
					rootDir.mkdirs();
				}

				progressInfoBean.setUnkownProgress(true);
				progressInfoBean.setTask("迁移工作区");

				requestStatus.setRequestId(progressInfoBean.getId());

				request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

				try {

					scmServer.switchTo(rootDir, newSvnUrl, moduleInfo, new DefaultSCMListener() {

						@Override
						public void onProgress(String task, long progress, long total) {
							System.out.println(progress + " - " + total);
						}

						@Override
						public void logMessage(String arg0) {

							progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
						}

						@Override
						public void logError(String arg0) {
							System.out.println(arg0);
							requestStatus.setFinished(true);
							requestStatus.setSuccess(false);
							requestStatus.setMessage(arg0);
							request.getSession().removeAttribute(progressInfoBean.getId());
						}

						@Override
						public void logCompleted(String arg0) {
							System.out.println(arg0);
							requestStatus.setFinished(true);
							requestStatus.setSuccess(true);
							requestStatus.setMessage(arg0);
							request.getSession().removeAttribute(progressInfoBean.getId());
						}

						@Override
						public void logCommandLine(String arg0) {
							progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
						}
					});
				} catch (Exception e) {
					requestStatus.setFinished(true);
					requestStatus.setSuccess(false);
					requestStatus.setMessage(e.getMessage());
					request.getSession().removeAttribute(progressInfoBean.getId());
				}

			} else {
				requestStatus.setFinished(true);
				requestStatus.setSuccess(true);
				request.getSession().removeAttribute(progressInfoBean.getId());
			}
		}
		//

		requestStatus.setData(scmConfigBean);

		WORKSPACE_SERVICE.saveWorkspaceScmConfig(scmConfigBean);

		return requestStatus;
	}

	@RequestMapping("/checkSaveWorkspaceScmProgress")
	@ResponseBody
	public ProgressInfoBean checkSaveWorkspaceScmProgress(@RequestParam long workspaceId,
			final HttpServletRequest request) throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("relocalWorkspace" + workspaceId);

	}

	@RequestMapping("/checkImportWorkspaceFromScmProgress")
	@ResponseBody
	public ProgressInfoBean checkImportWorkspaceFromScmProgress(@RequestParam long workspaceId,
			final HttpServletRequest request) throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("importWorkspace" + workspaceId);

	}

	@RequestMapping("/checkUpdateWorkspaceFromScmProgress")
	@ResponseBody
	public ProgressInfoBean checkUpdateWorkspaceFromScmProgress(@RequestParam long workspaceId,
			final HttpServletRequest request) throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("updateWorkspace" + workspaceId);

	}

	@RequestMapping("/updateWorkspaceFromScm")
	@ResponseBody
	public RequestStatus updateWorkspaceFromScm(@ModelAttribute WorkspaceScmConfigBean scmConfigBean,
			final HttpServletRequest request) throws Exception {
		final RequestStatus requestStatus = new RequestStatus();

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(scmConfigBean.getWorkspaceId());

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (rootDir.exists() == false) {
			rootDir.mkdirs();
		}

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		progressInfoBean.setId("updateWorkspace" + scmConfigBean.getWorkspaceId());

		progressInfoBean.setUnkownProgress(true);
		progressInfoBean.setTask("更新工作区");

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		try {
			scmServer.updateResource(rootDir, moduleInfo, new DefaultSCMListener() {

				@Override
				public void onProgress(String task, long progress, long total) {
					System.out.println(progress + " - " + total);
				}

				@Override
				public void logMessage(String arg0) {

					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}

				@Override
				public void logError(String arg0) {
					System.out.println(arg0);
					requestStatus.setFinished(true);
					requestStatus.setSuccess(false);
					requestStatus.setMessage(arg0);
					request.getSession().removeAttribute(progressInfoBean.getId());
				}

				@Override
				public void logCompleted(String arg0) {
					System.out.println(arg0);
					requestStatus.setFinished(true);
					requestStatus.setSuccess(true);
					requestStatus.setMessage(arg0);
					request.getSession().removeAttribute(progressInfoBean.getId());
				}

				@Override
				public void logCommandLine(String arg0) {
					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}
			});
		} catch (Exception e) {
			requestStatus.setFinished(true);
			requestStatus.setSuccess(false);
			requestStatus.setMessage(e.getMessage());
			request.getSession().removeAttribute(progressInfoBean.getId());
		}

		return requestStatus;

	}

	@RequestMapping("/hasImportWorkspaceFromScm")
	@ResponseBody
	public String hasImportWorkspaceFromScm(@RequestParam long workspaceId, final HttpServletRequest request)
			throws Exception {

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE.getWorkspaceScmConfig(workspaceId);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (scmConfigBean.getScmType().equals("SVN_SERVER")) {
			return String.valueOf(new File(rootDir, ".svn").exists());
		} else if (scmConfigBean.getScmType().equals("GIT_SERVER")) {
			return String.valueOf(new File(rootDir, ".git").exists());
		} else {
			return "false";
		}
	}

	@RequestMapping("/importWorkspaceFromScm")
	@ResponseBody
	public RequestStatus importWorkspaceFromScm(@ModelAttribute WorkspaceScmConfigBean scmConfigBean,
			final HttpServletRequest request) throws Exception {

		final RequestStatus requestStatus = new RequestStatus();

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(scmConfigBean.getWorkspaceId());

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (rootDir.exists() == false) {
			rootDir.mkdirs();
		} else {
			FileUtils.cleanDirectory(rootDir);
		}

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		progressInfoBean.setId("importWorkspace" + scmConfigBean.getWorkspaceId());
		progressInfoBean.setUnkownProgress(true);
		progressInfoBean.setTask("导入工作区");
		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		try {
			scmServer.checkoutResource(rootDir, moduleInfo, new DefaultSCMListener() {

				@Override
				public void logMessage(String arg0) {

					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}

				@Override
				public void logError(String arg0) {
					System.out.println(arg0);
					requestStatus.setFinished(true);
					requestStatus.setSuccess(false);
					requestStatus.setMessage(arg0);
					request.getSession().removeAttribute(progressInfoBean.getId());
				}

				@Override
				public void logCompleted(String arg0) {
					System.out.println(arg0);
					requestStatus.setFinished(true);
					requestStatus.setSuccess(true);
					requestStatus.setMessage(arg0);
					request.getSession().removeAttribute(progressInfoBean.getId());
				}

				@Override
				public void logCommandLine(String arg0) {
					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}
			});
		} catch (Exception e) {
			requestStatus.setFinished(true);
			requestStatus.setSuccess(false);
			requestStatus.setMessage(e.getMessage());
			request.getSession().removeAttribute(progressInfoBean.getId());
		}

		return requestStatus;
	}

	@RequestMapping("/saveWorkspaceResource")
	@ResponseBody
	public WorkspaceResourceBean saveWorkspaceResource(@RequestParam long workspaceId,
			@ModelAttribute WorkspaceResourceBean resourceBean, final HttpServletRequest request) throws Exception {

		resourceBean.setWorkspaceId(workspaceId);

		if (resourceBean.getId() == 0) {
			WORKSPACE_SERVICE.addWorkspaceResource(resourceBean);
		} else {
			WORKSPACE_SERVICE.modifyWorkspaceResource(resourceBean);
		}

		return resourceBean;

	}

	@RequestMapping("/removeWorkspaceResources")
	@ResponseBody
	public boolean removeWorkspaceResources(@RequestParam long[] workspaceResourceIds) throws Exception {

		for (int i = 0; i < workspaceResourceIds.length; i++) {
			WORKSPACE_SERVICE.deleteWorkspaceResource(workspaceResourceIds[i]);
		}

		return true;
	}

	@RequestMapping("/getWorkspaceResourceById")
	@ResponseBody
	public WorkspaceResourceBean getWorkspaceResourceById(@RequestParam long id) throws Exception {
		return WORKSPACE_SERVICE.getWorkspaceResourceById(id);
	}

	@RequestMapping("/getWorkspaceResources")
	@ResponseBody
	public WorkspaceResourceBean[] getWorkspaceResources(@RequestParam long workspaceId,
			@RequestParam String resourceType) throws Exception {
		return WORKSPACE_SERVICE.getWorkspaceResources(workspaceId,
				new WorkspaceResourceTypeEnum[] { WorkspaceResourceTypeEnum.getEnum(resourceType) });
	}

	@RequestMapping("/getFileContentInfo")
	@ResponseBody
	public FileInfoBean getFileContentInfo(@RequestParam long workspaceId, @RequestParam String path) throws Exception {
		FileInfoBean fileInfoBean = new FileInfoBean();

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		File file = new File(SystemUtils.USER_HOME, this.getConfig("workspace.rootDir") + path);

		if (file.exists()) {
			SourceLineBean sourceLineBean = SourceLineCounter.parse(file);
			fileInfoBean.setCodeLines(sourceLineBean.getCodeLines());
			fileInfoBean.setBlankLines(sourceLineBean.getBlankLines());
			fileInfoBean.setCommentLines(sourceLineBean.getCommentLines());
			fileInfoBean.setName(file.getName());
			fileInfoBean.setPath(file.getParent());
			fileInfoBean.setType(file.isFile() ? "file" : "folder");
			fileInfoBean.setFileType(FilenameUtils.getExtension(path));
			fileInfoBean.setContent(FileUtils.readFileToString(file, "UTF-8"));
		}

		return fileInfoBean;
	}

	@RequestMapping("/checkFileSourceCode")
	@ResponseBody
	public SourceCodeCheckRuleSet[] checkFileSourceCode(@RequestParam String path) throws Exception {

		String[] fileIds = StringUtils.split(path, "@", 2);

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(Long.parseLong(fileIds[0]));

		String fileType = FilenameUtils.getExtension(fileIds[1]);

		SourceCodeCheckRuleSet[] checkRuleSets = SourceCodeCheckUtils.checkSourceCode(fileIds[1], fileType, "1.7");

		return checkRuleSets;
	}

	@RequestMapping("/checkResourceFiles")
	@ResponseBody
	public RequestStatus checkResourceFiles(@RequestParam long workspaceResourceId,
			@RequestParam(required = false) String priority, @RequestParam(required = false) String fileType,
			final HttpServletRequest request) throws Exception {

		final RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		progressInfoBean.setId("checkResourceCode" + workspaceResourceId);
		progressInfoBean.setTask("检查代码");
		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		WorkspaceResourceBean workspaceResourceBean = WORKSPACE_SERVICE.getWorkspaceResourceById(workspaceResourceId);

		File workspaceDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceResourceBean.getWorkspacePath());

		if (workspaceDir.exists() == false) {
			workspaceDir.mkdirs();
		}

		File resourceDir = new File(workspaceDir, workspaceResourceBean.getResourcePath());

		if (resourceDir.exists() == false) {
			resourceDir.mkdirs();
		}

		Map<String, String[]> fileTypeLanguageMap = new HashMap<>();

		if (StringUtils.isNotEmpty(fileType)) {

			String[] fileTypes = StringUtils.split(fileType, ",");

			for (int i = 0; i < fileTypes.length; i++) {
				if ("java".equals(fileTypes[i])) {
					fileTypeLanguageMap.put(fileTypes[i], new String[] { fileTypes[i], "1.7" });
				} else if ("js".equals(fileTypes[i])) {
					fileTypeLanguageMap.put(fileTypes[i], new String[] { "ecmascrpt" });
				} else {
					fileTypeLanguageMap.put(fileTypes[i], new String[] { fileTypes[i] });
				}
			}
		}

		String[] prioritys = StringUtils.split(priority, ",");

		SourceCodeCheckRuleSet[] checkRuleSets = SourceCodeCheckUtils.batchCheckSourceCode(resourceDir.getPath(),
				prioritys, fileTypeLanguageMap, new ISourceCodeCheckListtener() {

					@Override
					public void start() {

					}

					@Override
					public void setTotal(long total) {
						progressInfoBean.setTotalCount(total);
					}

					@Override
					public void setProgress(long progress) {
						progressInfoBean.setValue(progress);
					}

					@Override
					public void setMessage(String message) {
						progressInfoBean.setProgressMessage(message);
					}

					@Override
					public void finished() {
						requestStatus.setFinished(true);
						requestStatus.setSuccess(true);
						request.getSession().removeAttribute(progressInfoBean.getId());
					}
				});
		requestStatus.setFinished(true);
		requestStatus.setSuccess(true);
		requestStatus.setData(checkRuleSets);
		return requestStatus;
	}

	@RequestMapping("/getFileBasicInfo")
	@ResponseBody
	public FileInfoBean getFileBasicInfo(@RequestParam long workspaceId, @RequestParam String path) throws Exception {
		FileInfoBean fileInfoBean = new FileInfoBean();

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		File file = new File(SystemUtils.USER_HOME, this.getConfig("workspace.rootDir") + path);

		if (file.exists()) {
			SourceLineBean sourceLineBean = SourceLineCounter.parse(file);
			fileInfoBean.setCodeLines(sourceLineBean.getCodeLines());
			fileInfoBean.setBlankLines(sourceLineBean.getBlankLines());
			fileInfoBean.setCommentLines(sourceLineBean.getCommentLines());
			fileInfoBean.setName(file.getName());
			fileInfoBean.setPath(file.getPath());
			fileInfoBean.setType(file.isFile() ? "file" : "folder");
			fileInfoBean.setFileType(FilenameUtils.getExtension(path));
			fileInfoBean.setFileSize(FileUtils.byteCountToDisplaySize(file.length()));
			fileInfoBean.setLastModifyTime(DateFormatUtils.format(file.lastModified(), "yyyy-MM-dd HH:mm:ss"));
		}

		return fileInfoBean;
	}

	@RequestMapping("/queryWorkspaceResourceRelatedBusinessPackages")
	@ResponseBody
	public GridBean queryWorkspaceResourceRelatedBusinessPackages(
			@ModelAttribute ResourceRelatedBusinessPackageSearchModel searchModel, HttpServletRequest request,
			Model model) throws Exception {
		AbstractSearchHelper<WorkspaceResourceBusinessPackageRelateDAOQueryBean, ResourceRelatedBusinessPackageSearchModel> searchHelper = new AbstractSearchHelper<WorkspaceResourceBusinessPackageRelateDAOQueryBean, ResourceRelatedBusinessPackageSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(WorkspaceResourceBusinessPackageRelateDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceResourceBusinessPackageCount(queryBean);
			}

			@Override
			protected Object[] queryData(WorkspaceResourceBusinessPackageRelateDAOQueryBean queryBean)
					throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceResourceBusinessPackages(queryBean);
			}

			@Override
			protected WorkspaceResourceBusinessPackageRelateDAOQueryBean createQueryBean() {
				return new WorkspaceResourceBusinessPackageRelateDAOQueryBean();
			}
		};

		return searchHelper.doSearch(request);
	}

	@RequestMapping("/addWorkspaceResourceModelPackages")
	@ResponseBody
	public boolean addWorkspaceResourceModelPackages(@RequestParam long workspaceResourceId,
			@RequestParam(value = "modelPackageIds") long[] modelPackageIds) throws Exception {

		WORKSPACE_SERVICE.addWorkspaceResourceBusinessPackageRelate(workspaceResourceId, modelPackageIds);

		return true;

	}

	@RequestMapping("/removeWorkspaceResourceModelPackages")
	@ResponseBody
	public boolean removeWorkspaceResourceModelPackages(@RequestParam(value = "ids") long[] ids) throws Exception {

		WORKSPACE_SERVICE.removeWorkspaceResourceBusinessPackageRelates(ids);

		return true;

	}

	@RequestMapping("/checkGenWorkspaceResourceSourceCode")
	@ResponseBody
	public ProgressInfoBean checkGenWorkspaceResourceSourceCode(@RequestParam long workspaceResourceId,
			final HttpServletRequest request) throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("genResourceCode" + workspaceResourceId);

	}

	@RequestMapping("/checkGenWorkspaceSourceCode")
	@ResponseBody
	public ProgressInfoBean checkGenWorkspaceSourceCode(@RequestParam long workspaceId,
			final HttpServletRequest request) throws Exception {

		ProgressInfoBean progressInfoBean = (ProgressInfoBean) request.getSession()
				.getAttribute("genWorkspaceCode" + workspaceId);

		return progressInfoBean;

	}

	@RequestMapping("/genWorkspaceSourceCode")
	@ResponseBody
	public RequestStatus genWorkspaceSourceCode(@RequestParam long workspaceId,
			@RequestParam(required = false, name = "resourceRelateModelPackageIds[]") long[] relateModelPackageIds,
			@RequestParam(required = false, name = "resourceRelateModelPackageIds") long[] resourceRelateModelPackageIds,
			final HttpServletRequest request) throws Exception {

		final RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		//final Formatter formatter = new Formatter();

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE.getWorkspaceScmConfig(workspaceId);

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File workspaceDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (workspaceDir.exists() == false) {
			workspaceDir.mkdirs();
		}

		progressInfoBean.setId("genWorkspaceCode" + workspaceId);

		progressInfoBean.setTask("更新工作区代码");

		try {

			scmServer.updateResource(workspaceDir, moduleInfo, new DefaultSCMListener() {

				@Override
				public void logCommandLine(String arg0) {
					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}

				@Override
				public void logError(String error) {
					progressInfoBean.setProgressMessage("更新工作区代码错误:" + error);
				}

			});

		} catch (Exception e) {

			requestStatus.setFinished(true);

			requestStatus.setSuccess(false);

			requestStatus.setMessage(e.getMessage());

			request.getSession().removeAttribute(progressInfoBean.getId());

			return requestStatus;
		}

		progressInfoBean.setTask("生成代码");

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		VelocityEngine velocityEngine = new VelocityEngine();

		Map<String, Object> vmContenxt = new HashMap<>();

		WorkspaceConfigPropertyBean[] configPropertyBeans = WORKSPACE_SERVICE
				.getWorkspaceConfigPropertiesByConfigItem(workspaceId, "generator.DAO");

		for (int i = 0; i < configPropertyBeans.length; i++) {
			vmContenxt.put(configPropertyBeans[i].getConfigProperty(), configPropertyBeans[i].getConfigValue());
		}

		WorkspaceResourceBusinessPackageRelateDAOQueryBean resourceBusinessPackageRelateDAOQueryBean = new WorkspaceResourceBusinessPackageRelateDAOQueryBean();

		if (relateModelPackageIds != null) {
			resourceBusinessPackageRelateDAOQueryBean.createCriteria().andIdIn(relateModelPackageIds);
		} else if (resourceRelateModelPackageIds != null) {
			resourceBusinessPackageRelateDAOQueryBean.createCriteria().andIdIn(resourceRelateModelPackageIds);

		}

		WorkspaceResourceBusinessPackageRelateBean[] relateBeans = WORKSPACE_SERVICE
				.queryWorkspaceResourceBusinessPackages(resourceBusinessPackageRelateDAOQueryBean);

		ProductModelCodeTemplateDAOQueryBean queryBean = new ProductModelCodeTemplateDAOQueryBean();

		ProductModelObjectDAOQueryBean modelObjectQueryBean = new ProductModelObjectDAOQueryBean();

		StringBuffer comment = new StringBuffer("生成");

		int totalCount = 0;

		int progressValue = 0;

		List<ProductModelPackageBean> packageBeans = new ArrayList<>();

		Map<Long, List<ProductModelCodeTemplateBean>> codeTemplateMap = new HashMap<>();

		Map<Long, List<ProductModelObjectBean>> modelObjectBeanMap = new HashMap<>();

		Map<Long, File> packageDirMap = new HashMap<>();

		Map<String, File> resourceDirMap = new HashMap<>();

		for (int i = 0; i < relateBeans.length; i++) {

			WorkspaceResourceBusinessPackageRelateBean workspaceResourceBusinessPackageRelateBean = relateBeans[i];

			if (i > 0) {
				comment.append(",");
			}
			comment.append(workspaceResourceBusinessPackageRelateBean.getBusinessPackageName());

			ProductModelPackageBean modelPackageBean = PRODUCT_MODEL_SERVICE
					.getProductModelPackageById(workspaceResourceBusinessPackageRelateBean.getBusinessPcakageId());

			packageBeans.add(modelPackageBean);

			if (resourceDirMap.containsKey(workspaceResourceBusinessPackageRelateBean.getResourcePath()) == false) {
				File resourceDir = new File(workspaceDir, workspaceResourceBusinessPackageRelateBean.getResourcePath());

				if (resourceDir.exists() == false) {
					resourceDir.mkdirs();
				}

				resourceDirMap.put(workspaceResourceBusinessPackageRelateBean.getResourcePath(), resourceDir);
			}

			File packageDir = new File(resourceDirMap.get(workspaceResourceBusinessPackageRelateBean.getResourcePath()),
					StringUtils.replace(modelPackageBean.getPackageName(), ".", SystemUtils.FILE_SEPARATOR));

			if (packageDir.exists() == false) {
				packageDir.mkdirs();
			}

			packageDirMap.put(modelPackageBean.getId(), packageDir);

			queryBean.clear();

			if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("DAO")) {
				queryBean.createCriteria().andTargetTypeEqualTo("DAO");
			} else if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("SERVICE")) {
				queryBean.createCriteria().andTargetTypeIn(new String[] { "DTO", "ENUM", "SERVICE" });
			}

			ProductModelCodeTemplateBean[] templateBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelCodeTemplates(queryBean);

			codeTemplateMap.put(modelPackageBean.getId(), Arrays.asList(templateBeans));

			modelObjectQueryBean.clear();

			ProductModelObjectDAOQueryBean.Criteria criteria = modelObjectQueryBean.createCriteria();

			criteria.andPackageIdEqualTo(workspaceResourceBusinessPackageRelateBean.getBusinessPcakageId());

			if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("DAO")) {
				criteria.andObjectTypeEqualTo("DAO");
			} else if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("SERVICE")) {
				criteria.andObjectTypeIn(new String[] { "DTO", "ENUM", "SERVICE" });
			}

			ProductModelObjectBean[] modelObjectBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelObjects(modelObjectQueryBean);

			for (int j = 0; j < templateBeans.length; j++) {

				if ("MODEL_PACKAGE".equals(templateBeans[j].getInputObjectType())) {
					totalCount++;
				} else if ("MODEL_OBJECT".equals(templateBeans[j].getInputObjectType())) {
					for (int k = 0; k < modelObjectBeans.length; k++) {
						if (modelObjectBeans[k].getObjectType().equals(templateBeans[j].getTargetType())) {
							totalCount++;
							if (modelObjectBeanMap.containsKey(modelPackageBean.getId()) == false) {
								modelObjectBeanMap.put(modelPackageBean.getId(),
										new ArrayList<ProductModelObjectBean>());
							}
							if (modelObjectBeanMap.get(modelPackageBean.getId())
									.contains(modelObjectBeans[k]) == false) {
								modelObjectBeanMap.get(modelPackageBean.getId()).add(modelObjectBeans[k]);
							}

						}
					}
				}
			}
		}

		progressInfoBean.setTotalCount(totalCount);

		for (Iterator<ProductModelPackageBean> iterator = packageBeans.iterator(); iterator.hasNext();) {

			ProductModelPackageBean packageBean = iterator.next();

			List<ProductModelCodeTemplateBean> codeTemplateBeans = codeTemplateMap.get(packageBean.getId());

			List<ProductModelObjectBean> modelObjectBeans = modelObjectBeanMap.get(packageBean.getId());

			for (Iterator<ProductModelCodeTemplateBean> templateIterator = codeTemplateBeans
					.iterator(); templateIterator.hasNext();) {
				ProductModelCodeTemplateBean codeTemplateBean = templateIterator.next();

				File packageDir = packageDirMap.get(packageBean.getId());

				File codeDir = packageDir;

				if (StringUtils.isNotEmpty(codeTemplateBean.getFileOutputPath())) {
					codeDir = new File(packageDir, codeTemplateBean.getFileOutputPath());
					if (codeDir.exists() == false) {
						codeDir.mkdirs();
					}
				}

				if ("MODEL_OBJECT".equals(codeTemplateBean.getInputObjectType())) {

					for (Iterator<ProductModelObjectBean> objectIterator = modelObjectBeans.iterator(); objectIterator
							.hasNext();) {
						ProductModelObjectBean productModelObjectBean = objectIterator.next();

						if (productModelObjectBean.getObjectType().equals(codeTemplateBean.getTargetType()) == false) {
							continue;
						}

						String[] sourceCode = ProductModelCodeGenerator.generateProductModelObjectCode(velocityEngine,
								productModelObjectBean, codeTemplateBean, vmContenxt);

						progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(
								"生成[" + productModelObjectBean.getObjectName() + "]代码...", "...", 50));

						File packageSourceFile = new File(codeDir,
								sourceCode[0] + "." + codeTemplateBean.getFileType());

						if (packageSourceFile.exists() == false
								|| BooleanUtils.toBoolean(codeTemplateBean.getCanOverWrite())) {

							if (packageSourceFile.exists() == false) {
								packageSourceFile.createNewFile();
							}

//							if (codeTemplateBean.getFileType().equalsIgnoreCase("java")) {
//								sourceCode[1] = formatter.formatSourceAndFixImports(sourceCode[1]);
//							}

							FileUtils.write(packageSourceFile, sourceCode[1], "UTF-8");

						}
						progressInfoBean.setValue(++progressValue);
					}

				} else if ("MODEL_PACKAGE".equals(codeTemplateBean.getInputObjectType())) {

					String[] sourceCode = ProductModelCodeGenerator.generateProductModelPackageCode(velocityEngine,
							packageBean, modelObjectBeans.toArray(new ProductModelObjectBean[modelObjectBeans.size()]),
							codeTemplateBean, vmContenxt);
					progressInfoBean.setProgressMessage(
							StringUtils.abbreviateMiddle("生成[" + packageBean.getPackageName() + "]代码...", "...", 50));

					File packageSourceFile = new File(codeDir, sourceCode[0] + "." + codeTemplateBean.getFileType());

					if (packageSourceFile.exists() == false
							|| BooleanUtils.toBoolean(codeTemplateBean.getCanOverWrite())) {

						if (packageSourceFile.exists() == false) {
							packageSourceFile.createNewFile();
						}
						FileUtils.write(packageSourceFile, sourceCode[1], "UTF-8");
					}
					progressInfoBean.setValue(++progressValue);
				}

			}

		}

		comment.append("代码");

		progressInfoBean.setTask("提交代码");

		try {

			scmServer.commitResource(workspaceDir,resourceDirMap.values().toArray(new File[resourceDirMap.values().size()]),
					moduleInfo, comment.toString(), new DefaultSCMListener() {

						@Override
						public void logCommandLine(String arg0) {
							progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
						}

						@Override
						public void logError(String error) {
							progressInfoBean.setProgressMessage("提交代码错误:" + error);
						}

					});

			requestStatus.setFinished(true);

			requestStatus.setSuccess(true);

			// progressInfoBean.setFinsihed(true);

			// request.getSession().removeAttribute(progressInfoBean.getId());

			Date codeGenTime = new Date();

			for (int i = 0; i < relateBeans.length; i++) {
				WorkspaceResourceBusinessPackageRelateBean workspaceResourceBusinessPackageRelateBean = relateBeans[i];

				workspaceResourceBusinessPackageRelateBean.setLastGenCodeTime(codeGenTime);
				workspaceResourceBusinessPackageRelateBean.setSubmitterId(getLoginUserId());
				workspaceResourceBusinessPackageRelateBean.setSubmitterName(getLoginUserName());

				WORKSPACE_SERVICE.modifyWorkspaceResourceBusinessPackageRelates(relateBeans);
			}

			return requestStatus;

		} catch (Exception e) {

			requestStatus.setFinished(true);

			requestStatus.setSuccess(false);

			requestStatus.setMessage(e.getMessage());

			request.getSession().removeAttribute(progressInfoBean.getId());

			return requestStatus;
		}

	}

	@RequestMapping("/genWorkspaceResourceSourceCode")
	@ResponseBody
	public RequestStatus genWorkspaceResourceSourceCode(@RequestParam long workspaceResourceId,
			@RequestParam(required = false, name = "modelPackageIds") long[] modelPackageIds,
			final HttpServletRequest request) throws Exception {

		final RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		//final Formatter formatter = new Formatter();

		WorkspaceResourceBean workspaceResourceBean = WORKSPACE_SERVICE.getWorkspaceResourceById(workspaceResourceId);

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE
				.getWorkspaceScmConfig(workspaceResourceBean.getWorkspaceId());

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File workspaceDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceResourceBean.getWorkspacePath());

		if (workspaceDir.exists() == false) {
			workspaceDir.mkdirs();
		}

		File resourceDir = new File(workspaceDir, workspaceResourceBean.getResourcePath());

		if (resourceDir.exists() == false) {
			resourceDir.mkdirs();
		}

		progressInfoBean.setId("genResourceCode" + workspaceResourceId);

		progressInfoBean.setTask("更新工作区代码");

		try {

			scmServer.updateResource(resourceDir, moduleInfo, new DefaultSCMListener() {

				@Override
				public void logCommandLine(String arg0) {
					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}

				@Override
				public void logError(String error) {
					progressInfoBean.setProgressMessage("更新工作区代码错误:" + error);
				}

			});

		} catch (Exception e) {

			requestStatus.setFinished(true);

			requestStatus.setSuccess(false);

			requestStatus.setMessage(e.getMessage());

			request.getSession().removeAttribute(progressInfoBean.getId());

			return requestStatus;
		}

		progressInfoBean.setTask("生成代码");

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		VelocityEngine velocityEngine = new VelocityEngine();

		Map<String, Object> vmContenxt = new HashMap<>();

		WorkspaceConfigPropertyBean[] configPropertyBeans = WORKSPACE_SERVICE
				.getWorkspaceConfigPropertiesByConfigItem(workspaceResourceBean.getWorkspaceId(), "generator.DAO");

		for (int i = 0; i < configPropertyBeans.length; i++) {
			vmContenxt.put(configPropertyBeans[i].getConfigProperty(), configPropertyBeans[i].getConfigValue());
		}

		WorkspaceResourceBusinessPackageRelateBean[] relateBeans = WORKSPACE_SERVICE
				.getWorkspaceResourceBusinessPackageRelates(workspaceResourceId);

		if (ArrayUtils.isNotEmpty(modelPackageIds)) {
			List<WorkspaceResourceBusinessPackageRelateBean> relateList = new ArrayList<>();

			for (int i = 0; i < relateBeans.length; i++) {
				if (ArrayUtils.contains(modelPackageIds, relateBeans[i].getId())) {
					relateList.add(relateBeans[i]);
				}
			}

			relateBeans = relateList.toArray(new WorkspaceResourceBusinessPackageRelateBean[relateList.size()]);
		}

		ProductModelCodeTemplateDAOQueryBean queryBean = new ProductModelCodeTemplateDAOQueryBean();

		ProductModelObjectDAOQueryBean modelObjectQueryBean = new ProductModelObjectDAOQueryBean();

		StringBuffer comment = new StringBuffer("生成");

		int totalCount = 0;

		int progressValue = 0;

		List<ProductModelPackageBean> packageBeans = new ArrayList<>();

		Map<Long, List<ProductModelCodeTemplateBean>> codeTemplateMap = new HashMap<>();

		Map<Long, List<ProductModelObjectBean>> modelObjectBeanMap = new HashMap<>();

		Map<Long, File> packageDirMap = new HashMap<>();

		for (int i = 0; i < relateBeans.length; i++) {

			WorkspaceResourceBusinessPackageRelateBean workspaceResourceBusinessPackageRelateBean = relateBeans[i];

			if (i > 0) {
				comment.append(",");
			}
			comment.append(workspaceResourceBusinessPackageRelateBean.getBusinessPackageName());

			ProductModelPackageBean modelPackageBean = PRODUCT_MODEL_SERVICE
					.getProductModelPackageById(workspaceResourceBusinessPackageRelateBean.getBusinessPcakageId());

			packageBeans.add(modelPackageBean);

			File packageDir = new File(resourceDir,
					StringUtils.replace(modelPackageBean.getPackageName(), ".", SystemUtils.FILE_SEPARATOR));

			if (packageDir.exists() == false) {
				packageDir.mkdirs();
			}

			packageDirMap.put(modelPackageBean.getId(), packageDir);

			queryBean.clear();

			if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("DAO")) {
				queryBean.createCriteria().andTargetTypeEqualTo("DAO");
			} else if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("SERVICE")) {
				queryBean.createCriteria().andTargetTypeIn(new String[] { "DTO", "ENUM", "SERVICE" });
			}

			ProductModelCodeTemplateBean[] templateBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelCodeTemplates(queryBean);

			codeTemplateMap.put(modelPackageBean.getId(), Arrays.asList(templateBeans));

			modelObjectQueryBean.clear();

			ProductModelObjectDAOQueryBean.Criteria criteria = modelObjectQueryBean.createCriteria();

			criteria.andPackageIdEqualTo(workspaceResourceBusinessPackageRelateBean.getBusinessPcakageId());

			if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("DAO")) {
				criteria.andObjectTypeEqualTo("DAO");
			} else if (workspaceResourceBusinessPackageRelateBean.getBusinessPackageType().equals("SERVICE")) {
				criteria.andObjectTypeIn(new String[] { "DTO", "ENUM", "SERVICE" });
			}

			ProductModelObjectBean[] modelObjectBeans = PRODUCT_MODEL_SERVICE
					.queryProductModelObjects(modelObjectQueryBean);

			for (int j = 0; j < templateBeans.length; j++) {

				if ("MODEL_PACKAGE".equals(templateBeans[j].getInputObjectType())) {
					totalCount++;
				} else if ("MODEL_OBJECT".equals(templateBeans[j].getInputObjectType())) {
					for (int k = 0; k < modelObjectBeans.length; k++) {
						if (modelObjectBeans[k].getObjectType().equals(templateBeans[j].getTargetType())) {
							totalCount++;
							if (modelObjectBeanMap.containsKey(modelPackageBean.getId()) == false) {
								modelObjectBeanMap.put(modelPackageBean.getId(),
										new ArrayList<ProductModelObjectBean>());
							}
							if (modelObjectBeanMap.get(modelPackageBean.getId())
									.contains(modelObjectBeans[k]) == false) {
								modelObjectBeanMap.get(modelPackageBean.getId()).add(modelObjectBeans[k]);
							}

						}
					}
				}
			}
		}

		progressInfoBean.setTotalCount(totalCount);

		for (Iterator<ProductModelPackageBean> iterator = packageBeans.iterator(); iterator.hasNext();) {

			ProductModelPackageBean packageBean = iterator.next();

			List<ProductModelCodeTemplateBean> codeTemplateBeans = codeTemplateMap.get(packageBean.getId());

			List<ProductModelObjectBean> modelObjectBeans = modelObjectBeanMap.get(packageBean.getId());

			for (Iterator<ProductModelCodeTemplateBean> templateIterator = codeTemplateBeans
					.iterator(); templateIterator.hasNext();) {
				ProductModelCodeTemplateBean codeTemplateBean = templateIterator.next();

				File packageDir = packageDirMap.get(packageBean.getId());

				File codeDir = packageDir;

				if (StringUtils.isNotEmpty(codeTemplateBean.getFileOutputPath())) {
					codeDir = new File(packageDir, codeTemplateBean.getFileOutputPath());
					if (codeDir.exists() == false) {
						codeDir.mkdirs();
					}
				}

				if ("MODEL_OBJECT".equals(codeTemplateBean.getInputObjectType())) {

					for (Iterator<ProductModelObjectBean> objectIterator = modelObjectBeans.iterator(); objectIterator
							.hasNext();) {
						ProductModelObjectBean productModelObjectBean = objectIterator.next();

						if (productModelObjectBean.getObjectType().equals(codeTemplateBean.getTargetType()) == false) {
							continue;
						}

						String[] sourceCode = ProductModelCodeGenerator.generateProductModelObjectCode(velocityEngine,
								productModelObjectBean, codeTemplateBean, vmContenxt);

						progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(
								"生成[" + productModelObjectBean.getObjectName() + "]代码...", "...", 50));

						File packageSourceFile = new File(codeDir,
								sourceCode[0] + "." + codeTemplateBean.getFileType());

						if (packageSourceFile.exists() == false
								|| BooleanUtils.toBoolean(codeTemplateBean.getCanOverWrite())) {

							if (packageSourceFile.exists() == false) {
								packageSourceFile.createNewFile();
							}

//							if (codeTemplateBean.getFileType().equalsIgnoreCase("java")) {
//								sourceCode[1] = formatter.formatSourceAndFixImports(sourceCode[1]);
//							}

							FileUtils.write(packageSourceFile, sourceCode[1], "UTF-8");

						}
						progressInfoBean.setValue(++progressValue);
					}

				} else if ("MODEL_PACKAGE".equals(codeTemplateBean.getInputObjectType())) {

					String[] sourceCode = ProductModelCodeGenerator.generateProductModelPackageCode(velocityEngine,
							packageBean, modelObjectBeans.toArray(new ProductModelObjectBean[modelObjectBeans.size()]),
							codeTemplateBean, vmContenxt);
					progressInfoBean.setProgressMessage(
							StringUtils.abbreviateMiddle("生成[" + packageBean.getPackageName() + "]代码...", "...", 50));

					File packageSourceFile = new File(codeDir, sourceCode[0] + "." + codeTemplateBean.getFileType());

					if (packageSourceFile.exists() == false
							|| BooleanUtils.toBoolean(codeTemplateBean.getCanOverWrite())) {

						if (packageSourceFile.exists() == false) {
							packageSourceFile.createNewFile();
						}
						FileUtils.write(packageSourceFile, sourceCode[1], "UTF-8");
					}
					progressInfoBean.setValue(++progressValue);
				}

			}

		}

		comment.append("代码");

		progressInfoBean.setTask("提交代码");

		try {

			scmServer.commitResource(resourceDir, moduleInfo, comment.toString(), new DefaultSCMListener() {

				@Override
				public void logCommandLine(String arg0) {
					progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
				}

				@Override
				public void logError(String error) {
					progressInfoBean.setProgressMessage("提交代码错误:" + error);
				}

			});

			requestStatus.setFinished(true);

			requestStatus.setSuccess(true);

			request.getSession().removeAttribute(progressInfoBean.getId());

			Date codeGenTime = new Date();

			for (int i = 0; i < relateBeans.length; i++) {
				WorkspaceResourceBusinessPackageRelateBean workspaceResourceBusinessPackageRelateBean = relateBeans[i];

				workspaceResourceBusinessPackageRelateBean.setLastGenCodeTime(codeGenTime);
				workspaceResourceBusinessPackageRelateBean.setSubmitterId(getLoginUserId());
				workspaceResourceBusinessPackageRelateBean.setSubmitterName(getLoginUserName());
			}

			WORKSPACE_SERVICE.modifyWorkspaceResourceBusinessPackageRelates(relateBeans);

			return requestStatus;

		} catch (Exception e) {

			requestStatus.setFinished(true);

			requestStatus.setSuccess(false);

			requestStatus.setMessage(e.getMessage());

			request.getSession().removeAttribute(progressInfoBean.getId());

			return requestStatus;
		}

	}

	@RequestMapping("/queryResourceFileVersionInfo")
	@ResponseBody
	public GridBean queryResourceFileVersionInfo(@ModelAttribute ResourceVersionSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		try {
			AbstractNoQueryBeanSearchHelper<ResourceVersionSearchModel> searchHelper = new AbstractNoQueryBeanSearchHelper<ResourceVersionSearchModel>(
					searchModel) {

				@Override
				protected Object[] getData(ResourceVersionSearchModel searchModel) throws Exception {

					WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(searchModel.getWorkspaceId());

					WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE
							.getWorkspaceScmConfig(workspaceBean.getId());

					ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

					ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

					File rootDir = new File(SystemUtils.USER_HOME,
							getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

					if (rootDir.exists() == false) {
						rootDir.mkdirs();
					}

					String filePath = searchModel.getPath();

					if (StringUtils.startsWith(filePath, workspaceBean.getWorkspacePath())) {
						filePath = StringUtils.substringAfter(filePath, workspaceBean.getWorkspacePath() + "/");
					}

					VersionLogInformation[] informations = scmServer.showResourceLog(rootDir,
							new File[] { new File(rootDir, filePath) }, moduleInfo, null, null, null, false, null);

					ArrayUtils.reverse(informations);

					return informations;

				}
			};

			return searchHelper.doSearch(request);
		} catch (Exception e) {
			return new GridBean();
		}

	}

	@RequestMapping("/getResourceFileVersionInfo")
	@ResponseBody
	public VersionLogInformation[] getResourceFileVersionInfo(@RequestParam String path) throws Exception {

		String[] fileIds = StringUtils.split(path, "@", 2);

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(Long.parseLong(fileIds[0]));

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE.getWorkspaceScmConfig(workspaceBean.getId());

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (rootDir.exists() == false) {
			rootDir.mkdirs();
		}

		return scmServer.showResourceLog(rootDir, new File[] { new File(fileIds[1]) }, moduleInfo, null, null, null,
				false, new DefaultSCMListener() {

					@Override
					public void logCommandLine(String arg0) {
						System.out.println(arg0);
					}

				});
	}

	@RequestMapping("/checkGenScmReportProgress")
	@ResponseBody
	public ProgressInfoBean checkGenScmReportProgress(@RequestParam long workspaceId, final HttpServletRequest request)
			throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("genScmReport" + workspaceId);

	}

	@RequestMapping("/moveUpWorkspaceResource")
	@ResponseBody
	public boolean moveUpWorkspaceResource(@RequestParam long workspaceResourceId) throws Exception {

		WorkspaceResourceBean workspaceResource = WORKSPACE_SERVICE.getWorkspaceResourceById(workspaceResourceId);

		WorkspaceResourceDAOQueryBean queryBean = new WorkspaceResourceDAOQueryBean();

		queryBean.setSortProperty(IWorkspaceResourceDAO.OrderIndex);

		queryBean.createCriteria().andWorkspaceIdEqualTo(workspaceResource.getWorkspaceId());

		WorkspaceResourceBean[] resourceBeans = WORKSPACE_SERVICE.queryWorkspaceResources(queryBean);

		int index = ArrayUtils.indexOf(resourceBeans, workspaceResource);

		if (index != ArrayUtils.INDEX_NOT_FOUND && index != 0) {
			WorkspaceResourceBean willDownObj = resourceBeans[index - 1];
			resourceBeans[index - 1] = workspaceResource;
			resourceBeans[index] = willDownObj;
			for (int i = 0; i < resourceBeans.length; i++) {
				resourceBeans[i].setOrderIndex(i + 1);
				WORKSPACE_SERVICE.modifyWorkspaceResource(resourceBeans[i]);
			}
		}

		return true;
	}

	@RequestMapping("/moveDownWorkspaceResource")
	@ResponseBody
	public boolean moveDownWorkspaceResource(@RequestParam long workspaceResourceId) throws Exception {

		WorkspaceResourceBean workspaceResource = WORKSPACE_SERVICE.getWorkspaceResourceById(workspaceResourceId);

		WorkspaceResourceDAOQueryBean queryBean = new WorkspaceResourceDAOQueryBean();

		queryBean.setSortProperty(IWorkspaceResourceDAO.OrderIndex);

		queryBean.createCriteria().andWorkspaceIdEqualTo(workspaceResource.getWorkspaceId());

		WorkspaceResourceBean[] resourceBeans = WORKSPACE_SERVICE.queryWorkspaceResources(queryBean);

		int index = ArrayUtils.indexOf(resourceBeans, workspaceResource);

		if (index != ArrayUtils.INDEX_NOT_FOUND && index != resourceBeans.length - 1) {
			WorkspaceResourceBean willUpObj = resourceBeans[index + 1];
			resourceBeans[index + 1] = workspaceResource;
			resourceBeans[index] = willUpObj;
			for (int i = 0; i < resourceBeans.length; i++) {
				resourceBeans[i].setOrderIndex(i + 1);
				WORKSPACE_SERVICE.modifyWorkspaceResource(resourceBeans[i]);
			}
		}

		return true;
	}

	@RequestMapping("/compareWorkspaceResource")
	@ResponseBody
	public ResourceDiffentInfomation compareWorkspaceResource(@RequestParam long workspaceId, @RequestParam String path,
			@RequestParam String leftVersion, @RequestParam String rightVersion) throws Exception {

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE.getWorkspaceScmConfig(workspaceId);

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (rootDir.exists() == false) {
			rootDir.mkdirs();
		}

		String filePath = URLDecoder.decode(path, "UTF-8");

		if (StringUtils.startsWith(filePath, workspaceBean.getWorkspacePath())) {
			filePath = StringUtils.substringAfter(path, workspaceBean.getWorkspacePath() + "/");
		}

		return scmServer.showResourceDiffent(rootDir, new File(rootDir, filePath), leftVersion, rightVersion,
				moduleInfo, new DefaultSCMListener() {

					@Override
					public void logCommandLine(String arg0) {
						System.out.println(arg0);
					}

					@Override
					public void logMessage(String arg0) {
						System.out.println(arg0);
					}

				});
	}

	@RequestMapping("/genWorkspaceSCMReport")
	@ResponseBody
	public RequestStatus genWorkspaceSCMReport(@RequestParam long workspaceId, final HttpServletRequest request)
			throws Exception {

		final RequestStatus requestStatus = new RequestStatus();

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		WorkspaceScmConfigBean scmConfigBean = WORKSPACE_SERVICE.getWorkspaceScmConfig(workspaceId);

		ISCMService scmServer = WorkspaceUtils.getSCMService(scmConfigBean);

		ModuleInfoBean moduleInfo = WorkspaceUtils.getModuleInfo(scmConfigBean);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (rootDir.exists() == false) {
			rootDir.mkdirs();
		}

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		progressInfoBean.setTotalCount(100);

		progressInfoBean.setId("genScmReport" + scmConfigBean.getWorkspaceId());
		// progressInfoBean.setUnkownProgress(true);
		progressInfoBean.setTask("更新工作区");
		// progressInfoBean.setProgressStyle("progress-bar-success");

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		WorkspaceScmLogDAOQueryBean queryBean = new WorkspaceScmLogDAOQueryBean();

		queryBean.setSortProperty(IWorkspaceScmLogDAO.RevisionTime, false);

		queryBean.setMaxResults(1);

		queryBean.createCriteria().andWorkspaceIdEqualTo(scmConfigBean.getWorkspaceId())
				.andWorkspaceScmConfigIdEqualTo(scmConfigBean.getId());

		WorkspaceScmLogBean[] logBeans = WORKSPACE_SERVICE.queryWorkspaceScmLogs(queryBean);

		String startVersion = ArrayUtils.isNotEmpty(logBeans) ? logBeans[0].getRevision() : null;

		String endVersion = null;

		scmServer.updateResource(rootDir, moduleInfo, new DefaultSCMListener() {
			@Override
			public void logCommandLine(String arg0) {
				progressInfoBean.setValue(10);
				progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
			}

			@Override
			public void logError(String arg0) {
				// System.out.println(arg0);
				requestStatus.setFinished(true);
				requestStatus.setSuccess(false);
				requestStatus.setMessage(arg0);
			}

		});

		progressInfoBean.setProgressMessage("");

		// progressInfoBean.setUnkownProgress(false);
		progressInfoBean.setTask("收集报表数据");
		// progressInfoBean.setProgressStyle("progress-bar-warning");

		final VersionLogInformation[] informations = scmServer.scanResourceLog(rootDir, moduleInfo,
				WorkspaceUtils.getWorkspaceFileTypeConfigs(), startVersion, endVersion, new DefaultSCMListener() {

					@Override
					public void logCommandLine(String arg0) {
						System.out.println(arg0);
						progressInfoBean.setProgressMessage(StringUtils.abbreviateMiddle(arg0, "...", 50));
					}

					@Override
					public void onProgress(String task, long progress, long total) {

						double profress = ((double) progress / (double) total);
						BigDecimal profressvalue = BigDecimal.valueOf(profress * 80).setScale(2, RoundingMode.HALF_UP);
						progressInfoBean.setValue(10 + profressvalue.longValue());
					}

				});

		WorkspaceScmLogBean[] scmLogBeans = new WorkspaceScmLogBean[informations.length];

		for (int i = 0; i < informations.length; i++) {
			scmLogBeans[i] = new WorkspaceScmLogBean();
			addScmLogs(scmLogBeans[i], informations[i]);
		}

		// progressInfoBean.setUnkownProgress(true);
		progressInfoBean.setTask("更新报表数据");
		progressInfoBean.setProgressMessage("数据处理中,请稍候...");
		progressInfoBean.setValue(99);
		WORKSPACE_SERVICE.importWorkspaceScmLogs(scmConfigBean.getId(), scmLogBeans);

		requestStatus.setFinished(true);

		requestStatus.setSuccess(true);

		request.getSession().removeAttribute(progressInfoBean.getId());

		return requestStatus;
	}

	@RequestMapping("/getWorkspaceMemberById")
	@ResponseBody
	public WorkspaceMemberBean getWorkspaceMemberById(@RequestParam long id) throws Exception {
		return WORKSPACE_SERVICE.getWorkspaceMemberById(id);
	}

	@RequestMapping("/saveWorkspaceMember")
	@ResponseBody
	public WorkspaceMemberBean saveWorkspaceMember(@ModelAttribute WorkspaceMemberBean memberBean) throws Exception {
		WORKSPACE_SERVICE.modifyWorkspaceMember(memberBean);
		return memberBean;
	}

	@RequestMapping("/queryWorkspaceMembers")
	@ResponseBody
	public GridBean queryWorkspaceMembers(@ModelAttribute WorkspaceMemberSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		WorkspaceScmLogDAOQueryBean queryBean = new WorkspaceScmLogDAOQueryBean();

		queryBean.createCriteria().andWorkspaceIdEqualTo(searchModel.getWorkspaceId());

		queryBean.setSortProperty(IWorkspaceScmLogDAO.RevisionTime, false);

		WorkspaceScmLogBean[] scmLogBeans = WORKSPACE_SERVICE.queryWorkspaceScmLogs(queryBean);

		WorkspaceMemberDAOQueryBean memberQueryBean = new WorkspaceMemberDAOQueryBean();

		memberQueryBean.createCriteria().andWorkspaceIdEqualTo(searchModel.getWorkspaceId());

		WorkspaceMemberBean[] memberBeans = WORKSPACE_SERVICE.queryWorkspaceMembers(memberQueryBean);

		Map<String, WorkspaceMemberBean> memberMap = new HashMap<>();

		for (int i = 0; i < memberBeans.length; i++) {
			memberMap.put(memberBeans[i].getScmAccount(), memberBeans[i]);
		}

		for (int i = 0; i < scmLogBeans.length; i++) {
			WorkspaceScmLogBean workspaceScmLogBean = scmLogBeans[i];

			if (memberMap.containsKey(workspaceScmLogBean.getAuthor()) == false) {
				WorkspaceMemberBean memberBean = new WorkspaceMemberBean();
				memberBean.setLastActivityTime(workspaceScmLogBean.getRevisionTime());
				memberBean.setScmAccount(workspaceScmLogBean.getAuthor());
				memberBean.setWorkspaceId(searchModel.getWorkspaceId());
				WORKSPACE_SERVICE.addWorkspaceMember(memberBean);
				memberMap.put(workspaceScmLogBean.getAuthor(), memberBean);
			} else {
				WorkspaceMemberBean memberBean = memberMap.get(workspaceScmLogBean.getAuthor());
				if (memberBean.getLastActivityTime().getTime() < workspaceScmLogBean.getRevisionTime().getTime()) {
					memberBean.setLastActivityTime(workspaceScmLogBean.getRevisionTime());
					WORKSPACE_SERVICE.modifyWorkspaceMember(memberBean);
				}
			}
		}

		AbstractSearchHelper<WorkspaceMemberDAOQueryBean, WorkspaceMemberSearchModel> searchHelper = new AbstractSearchHelper<WorkspaceMemberDAOQueryBean, WorkspaceMemberSearchModel>(
				searchModel) {

			@Override
			protected WorkspaceMemberDAOQueryBean createQueryBean() {
				return new WorkspaceMemberDAOQueryBean();
			}

			@Override
			protected int queryCount(WorkspaceMemberDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceMemberCount(queryBean);
			}

			@Override
			protected Object[] queryData(WorkspaceMemberDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceMembers(queryBean);
			}

		};

		return searchHelper.doSearch(request);
	}

	@RequestMapping("/saveWorkspaceConfig")
	@ResponseBody
	public boolean saveWorkspaceConfig(@RequestParam long workspaceId, @RequestParam String configItem,
			@RequestParam("properties[]") String[] properties, @RequestParam("values[]") String[] values,
			HttpServletRequest request, Model model) throws Exception {

		WorkspaceConfigPropertyBean[] workspaceConfigPropertyBean = new WorkspaceConfigPropertyBean[properties.length];

		for (int i = 0; i < workspaceConfigPropertyBean.length; i++) {
			workspaceConfigPropertyBean[i] = new WorkspaceConfigPropertyBean();
			workspaceConfigPropertyBean[i].setConfigProperty(properties[i]);
			workspaceConfigPropertyBean[i].setConfigValue(values[i]);
		}

		WORKSPACE_SERVICE.setWorkspaceConfigPropertiesByConfigItem(workspaceId, configItem,
				workspaceConfigPropertyBean);

		return true;
	}

	@RequestMapping("/getWorkspaceConfig")
	@ResponseBody
	public WorkspaceConfigPropertyBean[] getWorkspaceConfig(@RequestParam long workspaceId,
			@RequestParam String configItem, HttpServletRequest request, Model model) throws Exception {

		return WORKSPACE_SERVICE.getWorkspaceConfigPropertiesByConfigItem(workspaceId, configItem);

	}

	protected void addScmLogs(WorkspaceScmLogBean scmLogBean, VersionLogInformation logInformation) {
		scmLogBean.setAuthor(logInformation.getAuthor());
		scmLogBean.setComment(logInformation.getComment());
		scmLogBean.setRevision(logInformation.getRevision());
		scmLogBean.setRevisionTime(logInformation.getRevisionTime());
		scmLogBean.setTotalLines(logInformation.getTotalLines());
		scmLogBean.setTotalSize(logInformation.getTotalSize());

		List<VersionLogChangePath> changePaths = logInformation.getChangePaths();

		WorkspaceScmChangePathLogBean[] changePathLogBeans = new WorkspaceScmChangePathLogBean[changePaths.size()];

		int index = 0;

		for (Iterator<VersionLogChangePath> iterator = changePaths.iterator(); iterator.hasNext();) {
			VersionLogChangePath versionLogChangePath = iterator.next();
			changePathLogBeans[index] = new WorkspaceScmChangePathLogBean();
			changePathLogBeans[index].setAction(versionLogChangePath.getAction());
			changePathLogBeans[index].setCopysrcpath(versionLogChangePath.getCopySrcPath());
			changePathLogBeans[index].setCopysrcrevision(versionLogChangePath.getCopySrcRevision());
			changePathLogBeans[index].setPath(versionLogChangePath.getPath());
			changePathLogBeans[index].setChangeLineCount(versionLogChangePath.getChangeLineCount());
			changePathLogBeans[index].setLineCount(versionLogChangePath.getLineCount());
			changePathLogBeans[index].setCommentLineCount(versionLogChangePath.getCommnetLineCount());
			changePathLogBeans[index].setBlankLineCount(versionLogChangePath.getBlankLineCount());
			changePathLogBeans[index].setFileSize(versionLogChangePath.getFileSize());
			index++;
		}

		scmLogBean.setChangePathLogs(changePathLogBeans);

		List<VersionLogInformation> childInfos = logInformation.getChildVersionLogs();

		WorkspaceScmLogBean[] childLogBeans = new WorkspaceScmLogBean[childInfos.size()];

		index = 0;

		for (Iterator<VersionLogInformation> iterator = childInfos.iterator(); iterator.hasNext();) {
			VersionLogInformation versionLogInformation = iterator.next();
			childLogBeans[index] = new WorkspaceScmLogBean();
			addScmLogs(childLogBeans[index], versionLogInformation);
			index++;
		}

		scmLogBean.setChildLogBeans(childLogBeans);
	}

	@RequestMapping("/queryWorkspaceDatabases")
	@ResponseBody
	public GridBean queryWorkspaceDatabases(@ModelAttribute WorkspaceDatabaseRelateSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {
		AbstractSearchHelper<WorkspaceProductDatabaseRelateDAOQueryBean, WorkspaceDatabaseRelateSearchModel> searchHelper = new AbstractSearchHelper<WorkspaceProductDatabaseRelateDAOQueryBean, WorkspaceDatabaseRelateSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(WorkspaceProductDatabaseRelateDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceProductDatabaseRelateCount(queryBean);
			}

			@Override
			protected Object[] queryData(WorkspaceProductDatabaseRelateDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceProductDatabaseRelates(queryBean);
			}

			@Override
			protected WorkspaceProductDatabaseRelateDAOQueryBean createQueryBean() {
				return new WorkspaceProductDatabaseRelateDAOQueryBean();
			}
		};

		return searchHelper.doSearch(request);
	}

	@RequestMapping("/saveWorkspaceDatabase")
	@ResponseBody
	public WorkspaceProductDatabaseRelateBean saveWorkspaceDatabase(
			@ModelAttribute WorkspaceProductDatabaseRelateBean relateBean) throws Exception {

		if (relateBean.getId() == 0) {
			WORKSPACE_SERVICE.addNewWorkspaceProductDatabaseRelate(relateBean);
		} else {
			WORKSPACE_SERVICE.modifyWorkspaceProductDatabaseRelate(relateBean);
		}

		return relateBean;
	}

	@RequestMapping("/deleteWorkspaceDatabases")
	@ResponseBody
	public boolean deleteWorkspaceDatabases(@RequestParam(name = "workspaceDatabaseIds[]") long[] workspaceDatabaseIds)
			throws Exception {

		WORKSPACE_SERVICE.deleteWorkspaceProductDatabaseRelates(workspaceDatabaseIds);

		return true;
	}

	@RequestMapping("/addWorkspaceDatabaseModels")
	@ResponseBody
	public boolean addWorkspaceDatabases(@RequestParam long workspaceDatabaseId,
			@RequestParam(name = "dbPackageIds[]") long[] dbPackageIds) throws Exception {

		for (int i = 0; i < dbPackageIds.length; i++) {

			WorkspaceProductDatabaseModelRelateBean modelRelateBean = new WorkspaceProductDatabaseModelRelateBean();

			modelRelateBean.setModelPcakageId(dbPackageIds[i]);
			modelRelateBean.setWorkspaceProductDatabaseRelateId(workspaceDatabaseId);
			WORKSPACE_SERVICE.addNewWorkspaceProductDatabaseModelRelate(modelRelateBean);

		}

		return true;
	}

	@RequestMapping("/queryWorkspaceDatabaseRelateModels")
	@ResponseBody
	public GridBean queryWorkspaceDatabaseRelateModels(
			@ModelAttribute WorkspaceDatabaseRelatedDBPackageSearchModel searchModel, HttpServletRequest request,
			Model model) throws Exception {
		AbstractSearchHelper<WorkspaceProductDatabaseModelRelateDAOQueryBean, WorkspaceDatabaseRelatedDBPackageSearchModel> searchHelper = new AbstractSearchHelper<WorkspaceProductDatabaseModelRelateDAOQueryBean, WorkspaceDatabaseRelatedDBPackageSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(WorkspaceProductDatabaseModelRelateDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceProductDatabaseModelRelateCount(queryBean);
			}

			@Override
			protected Object[] queryData(WorkspaceProductDatabaseModelRelateDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceProductDatabaseModelRelates(queryBean);
			}

			@Override
			protected WorkspaceProductDatabaseModelRelateDAOQueryBean createQueryBean() {
				return new WorkspaceProductDatabaseModelRelateDAOQueryBean();
			}
		};

		return searchHelper.doSearch(request);
	}

	@RequestMapping("/addWorkspaceDatabaseModelPackages")
	@ResponseBody
	public boolean addWorkspaceDatabaseModelPackages(@RequestParam long workspaceDatabaseId,
			@RequestParam(value = "modelPackageIds[]") long[] modelPackageIds) throws Exception {

		for (int i = 0; i < modelPackageIds.length; i++) {
			WorkspaceProductDatabaseModelRelateBean modelRelateBean = new WorkspaceProductDatabaseModelRelateBean();

			modelRelateBean.setWorkspaceProductDatabaseRelateId(workspaceDatabaseId);
			modelRelateBean.setModelPcakageId(modelPackageIds[i]);

			WORKSPACE_SERVICE.addNewWorkspaceProductDatabaseModelRelate(modelRelateBean);
		}

		return true;

	}

	@RequestMapping("/deleteWorkspaceDatabaseModelPackages")
	@ResponseBody
	public boolean deleteWorkspaceDatabaseModelPackages(@RequestParam(value = "ids[]") long[] ids) throws Exception {

		if (ArrayUtils.isNotEmpty(ids)) {

			WORKSPACE_SERVICE.deleteWorkspaceProductDatabaseModelRelates(ids);

		}

		return true;

	}

	public SingleConnectionDataSource getSingleConnectionDataSource(ProductDatabaseBean databaseServerBean) {

		SingleConnectionDataSource dataSource = new SingleConnectionDataSource();

		dataSource.setUsername(databaseServerBean.getDatabaseUser());
		dataSource.setPassword(databaseServerBean.getDatabasePassword());
		dataSource.setSuppressClose(true);

		if ("mysql".equalsIgnoreCase(databaseServerBean.getDatabaseType())) {

			dataSource.setDriverClassName("com.mysql.jdbc.Driver");

			dataSource.setUrl("jdbc:mysql://" + databaseServerBean.getDatabaseIp() + ":"
					+ databaseServerBean.getDatabasePort() + "/" + databaseServerBean.getDatabaseServiceId()
					+ "?useUnicode=true&characterEncoding=UTF-8");
		} else if ("oracle".equalsIgnoreCase(databaseServerBean.getDatabaseType())) {

			dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");

			dataSource.setUrl("jdbc:oracle:thin:@" + databaseServerBean.getDatabaseIp() + ":"
					+ databaseServerBean.getDatabasePort() + ":" + databaseServerBean.getDatabaseServiceId());
		} else if ("sqlserver".equalsIgnoreCase(databaseServerBean.getDatabaseType())) {

			dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

			dataSource.setUrl("jdbc:sqlserver://" + databaseServerBean.getDatabaseIp() + ":"
					+ databaseServerBean.getDatabasePort() + ";databaseName="
					+ databaseServerBean.getDatabaseServiceId());
		} else if ("sqlite".equalsIgnoreCase(databaseServerBean.getDatabaseType())) {
			dataSource.setDriverClassName("org.sqlite.JDBC");
			dataSource.setUrl("jdbc:sqlite://" + databaseServerBean.getDatabaseIp()
					+ databaseServerBean.getDatabaseServiceId() + ".sqlite");
		}

		return dataSource;

	}

	@RequestMapping("/checkUpdateDatabaseTables")
	@ResponseBody
	public ProgressInfoBean checkUpdateDatabaseTables(@RequestParam long databaseId, final HttpServletRequest request)
			throws Exception {

		return (ProgressInfoBean) request.getSession().getAttribute("updateDatabase" + databaseId);

	}

	@RequestMapping("/updateDatabaseTables")
	@ResponseBody
	public RequestStatus updateDatabaseTables(
			@RequestParam(name = "workspaceDatabaseModelIds[]") long[] workspaceDatabaseModelIds,
			final HttpServletRequest request) throws Exception {

		final RequestStatus requestStatus = new RequestStatus();

		final ProgressInfoBean progressInfoBean = new ProgressInfoBean();

		WorkspaceProductDatabaseModelRelateBean[] databaseModelRelateBeans = new WorkspaceProductDatabaseModelRelateBean[workspaceDatabaseModelIds.length];

		for (int i = 0; i < workspaceDatabaseModelIds.length; i++) {
			databaseModelRelateBeans[i] = WORKSPACE_SERVICE
					.getWorkspaceProductDatabaseModelRelateById(workspaceDatabaseModelIds[i]);
		}

		WorkspaceProductDatabaseRelateBean databaseRelateBean = WORKSPACE_SERVICE.getWorkspaceProductDatabaseRelateById(
				databaseModelRelateBeans[0].getWorkspaceProductDatabaseRelateId());

		progressInfoBean.setId("updateDatabase" + databaseRelateBean.getProductDatabaseId());

		progressInfoBean.setTask("更新数据库结构");

		progressInfoBean.setTotalCount(workspaceDatabaseModelIds.length);

		progressInfoBean.setProgressMessage("更新中，请稍候...");

		requestStatus.setRequestId(progressInfoBean.getId());

		request.getSession().setAttribute(progressInfoBean.getId(), progressInfoBean);

		final ProductDatabaseBean databaseBean = PRODUCT_MODEL_SERVICE
				.getProductDatabaseById(databaseRelateBean.getProductDatabaseId());

		final DataSource dataSource = getSingleConnectionDataSource(databaseBean);

		Platform platform = PlatformFactory.createNewPlatformInstance(dataSource);

		Database targetDatabase = platform.readModelFromDatabase(databaseBean.getDatabaseName());

		try {

			for (int i = 0; i < databaseModelRelateBeans.length; i++) {
				final File databaseXmlFile = getDatabaseTableXMLFile(databaseModelRelateBeans[i].getModelPcakageId(),
						databaseBean.getDatabaseServiceId());

				progressInfoBean.setProgressMessage("更新 " + databaseModelRelateBeans[i].getPackageName());

				databaseModelRelateBeans[i].setSubmitterId(getLoginUserId());

				databaseModelRelateBeans[i].setSubmitterName(getLoginUserName());

				databaseModelRelateBeans[i].setLastUpdateTime(new Date());

				DatabaseIO databaseIo = new DatabaseIO();
				databaseIo.setValidateXml(false);
				Database database = databaseIo.read(databaseXmlFile);

				Database changeDatabase = new Database();

				changeDatabase.setName(targetDatabase.getName());
				changeDatabase.setIdMethod(targetDatabase.getIdMethod());
				changeDatabase.setVersion(targetDatabase.getVersion());

				Table[] tables = database.getTables();

				for (int j = 0; j < tables.length; j++) {

					Table targetTable = targetDatabase.findTable(tables[j].getName(), false);

					if (targetTable != null) {
						changeDatabase.addTable(targetTable);
					}

				}

				if (changeDatabase.getTableCount() == 0) {
					platform.createModel(database, true, false);
				} else {
					platform.alterModel(database, changeDatabase, false);
				}

				progressInfoBean.setValue(i + 1);

				WORKSPACE_SERVICE.modifyWorkspaceProductDatabaseModelRelate(databaseModelRelateBeans[i]);

			}

			requestStatus.setFinished(true);
			requestStatus.setSuccess(true);

		} catch (Exception e) {
			requestStatus.setFinished(true);
			requestStatus.setSuccess(false);
			requestStatus.setMessage(e.getMessage());
			e.printStackTrace();
		}

		return requestStatus;

	}

	/*
	 * // sqlite 解析xml数据定义文件 public List<String> analysisDatabaseTableXMLFile(String
	 * path) throws Exception{ // 创建saxReader对象 SAXReader reader = new SAXReader();
	 * // 通过read方法读取一个文件 转换成Document对象 Document document = reader.read(new
	 * File(path)); //获取根节点元素对象 Element node = document.getRootElement(); //获取子节点
	 * Element element = node.element("table"); Element ele =
	 * node.element("column");
	 * 
	 * 
	 * }
	 */
	// 生成xml数据定义文件
	public File getDatabaseTableXMLFile(long packageId, String databaseName) throws Exception {

		ProductModelObjectDAOQueryBean queryObjectBean = new ProductModelObjectDAOQueryBean();

		queryObjectBean.createCriteria().andPackageIdEqualTo(packageId).andObjectTypeEqualTo("DB");

		ProductModelObjectBean[] objectBean = PRODUCT_MODEL_SERVICE.queryProductModelObjects(queryObjectBean);
		// 创建根节点database ;
		// Element root = DocumentHelper.createElement("database");
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("database", "http://db.apache.org/ddlutils/schema/1.1");
		root.addAttribute("name", databaseName);
		// root.addAttribute("xmlns","http://db.apache.org/ddlutils/schema/1.1");

		// 此处 for 循环可替换成 遍历 数据库表的结果集操作;
		for (int i = 0; i < objectBean.length; i++) {
			// 创建子节点
			Element elements = root.addElement("table");
			// 给table节点添加属性 name;
			elements.addAttribute("name", objectBean[i].getObjectName());
			elements.addAttribute("description", objectBean[i].getRemarks());
			// 给 table 节点添加子节点并赋值；
			ProductModelPropertyDAOQueryBean queryPropertyBean = new ProductModelPropertyDAOQueryBean();
			queryPropertyBean.createCriteria().andObjectIdEqualTo(objectBean[i].getId());
			ProductModelPropertyBean[] propertyBean = PRODUCT_MODEL_SERVICE
					.queryProductModelProperties(queryPropertyBean);
			for (int j = 0; j < propertyBean.length; j++) {
				elements.addElement("column").addAttribute("name", propertyBean[j].getPropertyName())
						.addAttribute("autoIncrement",
								StringUtils.isNotBlank(propertyBean[j].getIsAutoInc()) ? propertyBean[j].getIsAutoInc()
										: "false")
						.addAttribute("size", String.valueOf(propertyBean[j].getDataLength()))
						.addAttribute("type", propertyBean[j].getDataType())
						.addAttribute("required",
								StringUtils.isNotBlank(propertyBean[j].getIsAllowNull())
										? propertyBean[j].getIsAllowNull()
										: "false")
						.addAttribute("primaryKey",
								StringUtils.isNotBlank(propertyBean[j].getIsPrimaryKey())
										? propertyBean[j].getIsPrimaryKey()
										: "false");
			}

		}
		OutputFormat format = new OutputFormat();
		format.setEncoding("UTF-8");// 设置编码格式

		File databaseXmlFile = new File(
				SystemUtils.getJavaIoTmpDir() + "/" + databaseName + System.currentTimeMillis() + ".xml");

		if (databaseXmlFile.exists() == false) {
			databaseXmlFile.createNewFile();
		}

		XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(databaseXmlFile), format);

		xmlWriter.write(document);
		xmlWriter.close();

		return databaseXmlFile;
	}

	@RequestMapping("/queryWorspaceResouces")
	@ResponseBody
	public GridBean queryWorspaceResouces(@ModelAttribute WorkspaceResourceSearchModel searchModel,
			HttpServletRequest request, Model model) throws Exception {

		AbstractSearchHelper<WorkspaceResourceDAOQueryBean, WorkspaceResourceSearchModel> searchHelper = new AbstractSearchHelper<WorkspaceResourceDAOQueryBean, WorkspaceResourceSearchModel>(
				searchModel) {

			@Override
			protected int queryCount(WorkspaceResourceDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceResourceCount(queryBean);
			}

			@Override
			protected Object[] queryData(WorkspaceResourceDAOQueryBean queryBean) throws Exception {
				return WORKSPACE_SERVICE.queryWorkspaceResources(queryBean);
			}

			@Override
			protected WorkspaceResourceDAOQueryBean createQueryBean() {
				return new WorkspaceResourceDAOQueryBean();
			}
		};

		return searchHelper.doSearch(request);

	}

	@RequestMapping("/getWorspaceFileResouces")
	@ResponseBody
	public WorkspaceResourceFileBean[] getWorspaceFileResouces(@RequestParam long workspaceId,
			@RequestParam(required = false) String parentResourcePath, HttpServletRequest request, Model model)
			throws Exception {

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		File workspaceDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		if (StringUtils.isEmpty(parentResourcePath)) {
			parentResourcePath = workspaceBean.getWorkspacePath();
		}

		File rootDir = new File(SystemUtils.USER_HOME, this.getConfig("workspace.rootDir") + parentResourcePath);

		if (rootDir.exists() == false) {
			rootDir.mkdirs();
		}

		Collection<File> files = FileUtils.listFilesAndDirs(rootDir, new IOFileFilter() {

			@Override
			public boolean accept(File arg0, String arg1) {
				return arg0.getParentFile().equals(rootDir) && arg0.isHidden() == false;
			}

			@Override
			public boolean accept(File arg0) {
				return arg0.getParentFile().equals(rootDir) && arg0.isHidden() == false;
			}
		}, new IOFileFilter() {

			@Override
			public boolean accept(File arg0, String arg1) {
				return arg0.getParentFile().equals(rootDir) && arg0.isHidden() == false;
			}

			@Override
			public boolean accept(File arg0) {
				return arg0.getParentFile().equals(rootDir) && arg0.isHidden() == false;
			}
		});

		files.remove(rootDir);

		File[] fileArray = FileUtils.convertFileCollectionToFileArray(files);

		Arrays.sort(fileArray, new Comparator<File>() {

			@Override
			public int compare(File o1, File o2) {
				if (o1.isDirectory() && o2.isFile()) {
					return -1;
				} else if (o1.isFile() && o2.isDirectory()) {
					return 1;
				} else {
					return 0;
				}

			}

		});

		WorkspaceResourceFileBean[] resourceFileBeans = new WorkspaceResourceFileBean[fileArray.length];

		ISCMService iscmService = WorkspaceUtils.getSCMService(workspaceId);

		Map<String, VersionInfo> versionMap = iscmService.getResourceVersionInfos(workspaceDir, fileArray);

		for (int i = 0; i < resourceFileBeans.length; i++) {
			resourceFileBeans[i] = new WorkspaceResourceFileBean(workspaceBean, fileArray[i]);
			if (versionMap.containsKey(fileArray[i].getName())) {
				resourceFileBeans[i].setVersionInfo(versionMap.get(fileArray[i].getName()));
			}
		}

		return resourceFileBeans;
	}

	/**
	 * 查询下拉列表显示的资源目录
	 */
	@RequestMapping("/getFloderTreeSelect")
	@ResponseBody
	public TreeViewNodeBean[] getProductFeatureTreeSelect(@RequestParam long workspaceId, HttpServletRequest request,
			Model model) throws Exception {

		WorkspaceBean workspaceBean = WORKSPACE_SERVICE.getWorkspaceById(workspaceId);

		File rootDir = new File(SystemUtils.USER_HOME,
				this.getConfig("workspace.rootDir") + workspaceBean.getWorkspacePath());

		TreeViewNodeBean[] folderBeans = getSubFolders(rootDir, workspaceBean, null);

		return folderBeans;
	}

	protected TreeViewNodeBean[] getSubFolders(File parentFloder, WorkspaceBean workspaceBean,
			TreeViewNodeBean parentNodeBean) throws Exception {

		File[] subFloders = parentFloder.listFiles(new FileFilter() {

			@Override
			public boolean accept(File pathname) {
				return pathname.isDirectory() && pathname.isHidden() == false;
			}
		});

		List<TreeViewNodeBean> childNodes = new ArrayList<>();

		for (int i = 0; i < subFloders.length; i++) {
			File subFloder = subFloders[i];

			TreeViewNodeBean nodeBean = new TreeViewNodeBean();

			nodeBean.setNodeData(subFloder);

			nodeBean.setId(StringUtils.substringAfter(FilenameUtils.normalize(subFloder.getPath(), true),
					FilenameUtils.normalize(workspaceBean.getWorkspacePath() + "/", true)));

			nodeBean.setText(StringUtils.substringAfter(FilenameUtils.normalize(subFloder.getPath(), true),
					FilenameUtils.normalize(workspaceBean.getWorkspacePath() + "/", true)));

			childNodes.add(nodeBean);

			getSubFolders(subFloder, workspaceBean, nodeBean);
		}

		if (parentNodeBean != null) {
			parentNodeBean.setNodes(childNodes.toArray(new TreeViewNodeBean[childNodes.size()]));
		}

		return childNodes.toArray(new TreeViewNodeBean[childNodes.size()]);

	}

}
